package com.auxgroup.hr.front.site.co.performance;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.auxgroup.hr.front.site.inteceptor.SessionGain;
import com.auxgroup.hr.front.site.vo.performance.AssessItemDetailRespVO;
import com.auxgroup.hr.front.site.vo.performance.PerformanceReqVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auxgroup.hr.front.commons.BaseRetCode;
import com.auxgroup.hr.front.commons.enums.WfTypeEnum;
import com.auxgroup.hr.front.commons.utils.DateUtils;
import com.auxgroup.hr.front.commons.utils.ObjectFieldUtils;
import com.auxgroup.hr.front.commons.utils.Underline2Camel;
import com.auxgroup.hr.front.commons.vo.BaseResponseVO;
import com.auxgroup.hr.front.commons.vo.UserDTO;
import com.auxgroup.hr.front.dao.domain.PsCEpAppItem;
import com.auxgroup.hr.front.dao.domain.PsCEpAppItemR;
import com.auxgroup.hr.front.dao.domain.PsCEpAppRole;
import com.auxgroup.hr.front.dao.domain.PsCEpAppSec;
import com.auxgroup.hr.front.dao.domain.PsCEpDocVw;
import com.auxgroup.hr.front.dao.domain.PsCEpDocVwPrimary;
import com.auxgroup.hr.front.dao.domain.PsCEpEvaDocDv;
import com.auxgroup.hr.front.dao.domain.PsCEpPropsVw;
import com.auxgroup.hr.front.dao.domain.PsCListVw;
import com.auxgroup.hr.front.dao.repository.PsCEpEvaDocDvRepository;
import com.auxgroup.hr.front.dao.repository.PsCListVwRepository;
import com.auxgroup.hr.front.dao.repository.PsCWfEmpVwRepository;
import com.auxgroup.hr.front.service.performance.PerformancePlanService;
import com.auxgroup.hr.front.site.co.BaseCO;
import com.auxgroup.hr.front.site.inteceptor.SessionGain;
import com.auxgroup.hr.front.site.vo.performance.AssessItemDetailRespVO;
import com.auxgroup.hr.front.site.vo.performance.PerformanceReqVO;

/**
 * 绩效评估
 * @author lv-PC
 *
 */
@RestController
@RequestMapping("${auxgroup.hr.contextPath}/perassess")
public class PerformanceAssessCO extends BaseCO {

	@Autowired
	public PerformancePlanService  performancePlanService;
	
	@Autowired
	public PsCWfEmpVwRepository psCWfEmpVwRepository;
	
	@Autowired
	private PsCEpEvaDocDvRepository psCEpEvaDocDvRepository;
	
	@Autowired
	private PsCListVwRepository psCListVwRepository;
	
	@GetMapping("/itemDetail")
	public BaseResponseVO itemDetail(PerformanceReqVO reqVo, @SessionGain("user") UserDTO user){
		//获取绩效计划审批头表
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		PsCEpAppItem item = performancePlanService.getEpAppItem(docVw, new BigDecimal(reqVo.getSectionId()), reqVo.getCatType(), reqVo.getItemId());
		if(item==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		List<PsCEpPropsVw> props = performancePlanService.getItemProps(item.getcEpCatType());
		if(props==null||props.isEmpty()){
			return buildRespone(Collections.EMPTY_LIST);
		}
		AssessItemDetailRespVO respVo = new AssessItemDetailRespVO();
		respVo.setEvaType(docVw.getcEvaType());
		List<Map<String, Object>> respList = performancePlanService.buildRespItemDetail(props, item);
		//添加过往的评论信息
		performancePlanService.buildOldAssessInfo(respList, docVw, item);
		respVo.setDetailList(respList);
		respVo.setAssessSelect(buildModelSelects(docVw.getcEvaModel()));
		PsCEpAppItemR itemR = performancePlanService.getEpAppItemR(docVw, item.getcEpSectionId(), item.getcEpCatType(), item.getcEpCatItemId());
		if(itemR!=null){
			respVo.setComments(itemR.getComments());
			respVo.setScore(performancePlanService.getCommentScore(docVw.getcEvaType(), itemR, item.getcEpSectionType()));
		}
		return buildRespone(respVo,false);
	}
	
	
	
	private List<Map<String, Object>> buildModelSelects(String evaModel){
		//添加选项信息
		List<PsCEpEvaDocDv> evaDocs = psCEpEvaDocDvRepository.findAllByEvaModel(evaModel);
		List<Map<String, Object>> selects = new ArrayList<Map<String,Object>>();
		if(evaDocs!=null&&!evaDocs.isEmpty()){
			Map<String, Object> select;
			for (PsCEpEvaDocDv doc : evaDocs) {
				select = new HashMap<String, Object>();
				select.put("key", doc.getCEvaGrade());
				select.put("value", doc.getCEvaGrade());
				selects.add(select);
			}
		}
		return selects;
	}
	
	/**
	 * 保存评估内容
	 * @param reqVo
	 * @param score
	 * @param user
	 * @return
	 */
	@PostMapping("/saveassess")
	public BaseResponseVO saveassess(PerformanceReqVO reqVo,String score,@SessionGain("user") UserDTO user){
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		PsCEpAppItemR itemR = performancePlanService.saveEpAppItemR(docVw, reqVo.getComments(), score, reqVo.getCatType(),
				reqVo.getItemId(), new BigDecimal(reqVo.getSectionId()),user.getEmplId());
		if(itemR==null){
			return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),"评估意见保存失败");
		}
		return buildRespone();
	}
	
	
	/**
	 * 删除区段指标
	 * @param reqVo
	 * @return
	 */
	@PostMapping("/delitem")
	public BaseResponseVO delSecItem(PerformanceReqVO reqVo,@SessionGain("user") UserDTO user){
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		performancePlanService.delSecItem(docVw, reqVo.getSectionId(), reqVo.getCatType(), reqVo.getItemId());
		return buildRespone();
	}
	
	
	/**
	 * 保存区段指标
	 * @param reqVo
	 * @param itemJson
	 * @param user
	 * @return
	 */
	@PostMapping("/saveitem")
	public BaseResponseVO saveSecItemInfo(PerformanceReqVO reqVo,String itemJson,@SessionGain("user") UserDTO user){
		// itemJson 格式：[{"fieldName":"C_EP_XXX","fieldValue":"12346"}]
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		PsCEpAppItem item = buildItem(itemJson);
		if(item==null){
			return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),"保存失败，请稍后再试");
		}
		String score = getItemScore(itemJson, "score");
		String comments = getItemScore(itemJson, "COMMENTS");
		item.setcEpCatType(reqVo.getCatType());
		item.setcEpCatItemId(reqVo.getItemId());
		performancePlanService.saveEpAppItem(docVw, item, reqVo.getSectionId(),score,comments,user.getEmplId());
		return buildRespone();
	}
	
	/**
	 * 构建区段指标
	 * @param itemJson
	 * @return
	 */
	private PsCEpAppItem buildItem(String itemJson){
		if(StringUtils.isNotBlank(itemJson)){
			PsCEpAppItem item = new PsCEpAppItem();
			JSONArray reqs = JSONArray.parseArray(itemJson);
			for (int i = 0; i < reqs.size(); i++) {
				JSONObject json = reqs.getJSONObject(i);
				String fieldName = json.getString("fieldName");
				String camelFieldName = Underline2Camel.underline2Camel(fieldName, true);
				if(fieldName.startsWith("C_DATE")){
					ObjectFieldUtils.setFieldValueByName(camelFieldName, item, DateUtils.parseDate(json.getString("fieldValue"), DateUtils.FORMAT_DEFAULT));
				}else if(fieldName.startsWith("C_INT")||fieldName.startsWith("C_FLOAT")||fieldName.equals("EP_WEIGHT")){
					ObjectFieldUtils.setFieldValueByName(camelFieldName, item, new BigDecimal(json.getString("fieldValue")));
				}else{
					ObjectFieldUtils.setFieldValueByName(camelFieldName, item, json.getString("fieldValue"));
				}
			}
			return item;
		}
		return null;
	}
	
	
	private String getItemScore(String itemJson,String needFieldName){
		if(StringUtils.isNotBlank(itemJson)){
			JSONArray reqs = JSONArray.parseArray(itemJson);
			for (int i = 0; i < reqs.size(); i++) {
				JSONObject json = reqs.getJSONObject(i);
				String fieldName = json.getString("fieldName");
				if(needFieldName.equals(fieldName)){
					return json.getString("fieldValue");
				}
			}
		}
		return null;
	}
	
	
	
	/**
	 * 查询需要填写的字段
	 * @param reqVo
	 * @param user
	 * @return
	 */
	@GetMapping("/fields")
	public BaseResponseVO getNeedFiled(PerformanceReqVO reqVo,@SessionGain("user") UserDTO user){
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		PsCEpAppSec sec = performancePlanService.getEpAppSec(docVw, reqVo.getSectionId());
		if(sec==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		List<PsCEpPropsVw> props = performancePlanService.getItemProps(sec.getcEpCatType());
		PsCEpAppItem item = performancePlanService.getEpAppItem(docVw, new BigDecimal(reqVo.getSectionId()), reqVo.getCatType(), reqVo.getItemId());
		List<Map<String, Object>> fields = new ArrayList<Map<String,Object>>();
		if(props!=null&&!props.isEmpty()){
			Map<String, Object> field;
			for (PsCEpPropsVw prop : props) {
				if("EP_WEIGHT".equals(prop.getFieldname())){
					if(!"A".equals(sec.getcEpSectionType())){
						continue;
					}
				}
				field = new HashMap<String, Object>();
				field.put("title", prop.getLabelName());
				field.put("fieldName", prop.getFieldname());
				if(item!=null){
					field.put("fieldValue", performancePlanService.getSpecilOtherDesc(prop, item));
				}
				buildFieldType(field,prop);
				fields.add(field);
			}
			setScoreField(fields, docVw, item,sec.getcEpSectionType());
			return buildRespone(fields,false);
		}
		return buildRespone();
	}
	
	/**
	 * 设置字段类型及选项
	 * @param field
	 * @param prop
	 */
	private void buildFieldType(Map<String, Object> field,PsCEpPropsVw prop){
		if(prop.getFieldname().startsWith("C_DATE")){
			field.put("fileType", "DATE");
		}else if(prop.getFieldname().startsWith("C_YESNO")){
			field.put("fileType", "SELECT");
			List<Map<String, String>> selects = new ArrayList<Map<String,String>>();
			Map<String, String> yes = new HashMap<String, String>();
			yes.put("key", "Y");yes.put("value", "是");
			selects.add(yes);
			Map<String, String> no = new HashMap<String, String>();
			no.put("key", "N");no.put("value", "否");
			selects.add(no);
			field.put("selects", selects);
		}else if(prop.getFieldname().startsWith("C_PROMPT")){
			field.put("fileType", "SELECT");
			field.put("selects", getListbyListId(prop.getcListId()));
		}else{
			field.put("fileType", "TEXT");
		}
	}
	
	private List<Map<String, String>> getListbyListId(String listId){
		PsCListVw query = new PsCListVw();
		query.setcListId(listId);
		List<PsCListVw> lists = psCListVwRepository.findAll(Example.of(query));
		if(lists!=null&&!lists.isEmpty()){
			List<Map<String, String>> selects = new ArrayList<Map<String,String>>();
			Map<String, String> select;
			for (PsCListVw list : lists) {
				select = new HashMap<String, String>();
				select.put("key", list.getcListValue());
				select.put("value", list.getDescr100());
				selects.add(select);
			}
			return selects;
		}
		return null;
	}
	
	
	private void setScoreField(List<Map<String, Object>> fields,PsCEpDocVw docVw,PsCEpAppItem item,String sectionType){
		Map<String, Object> field;
		String score="";
		String comments="";
		if(item!=null){
			PsCEpAppItemR  itemR = performancePlanService.getEpAppItemR(docVw, item.getcEpSectionId(), item.getcEpCatType(), item.getcEpCatItemId());
			score = performancePlanService.getCommentScore(docVw.getcEvaType(), itemR, item.getcEpSectionType());
			comments = itemR.getComments();
		}
		
		
		if("B".equals(sectionType)){
			field = new HashMap<String, Object>();
			field.put("title", "加减分");
			field.put("fieldName", "score");
			field.put("fileType", "TEXT");
			if(StringUtils.isNotBlank(score)){
				field.put("fieldValue", score);
			}
			fields.add(field);
		}else{
			field = new HashMap<String, Object>();
			field.put("title", "评估结果");
			field.put("fieldName", "score");
			field.put("fileType", "SELECT");
			field.put("selects", buildModelSelects(docVw.getcEvaModel()));
			if(StringUtils.isNotBlank(score)){
				field.put("fieldValue", score);
			}
			fields.add(field);
			field = new HashMap<String, Object>();
			field.put("title", "评估意见");
			field.put("fieldName", "COMMENTS");
			field.put("fileType", "TEXT");
			if(StringUtils.isNotBlank(comments)){
				field.put("fieldValue", comments);
			}
			fields.add(field);
		}
		
		
	}
	
	/**
	 * 计算文档得分
	 * @param reqVo
	 * @param user
	 * @return
	 */
	@PostMapping("/calcpoint")
	public BaseResponseVO calcPoint(PerformanceReqVO reqVo,String evaType,@SessionGain("user") UserDTO user){
		if(StringUtils.isBlank(reqVo.getDocid())||StringUtils.isBlank(reqVo.getVersion())||StringUtils.isBlank(evaType)){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL.getRetCode(),"请求入参缺失");
		}
		Map<String, String> result = performancePlanService.calcPoint(reqVo.getDocid(), reqVo.getVersion(), user.getEmplId());
		if(result!=null&&"Y".equals(result.get("FLAG"))){
			if("A".equals(evaType)){
				return buildRespone(result.get("C_EP_SCORE"));
			}
			return buildRespone(result.get("C_EP_GRADE"));
		}else if(result!=null){
			return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),result.get("COMMENTS"));
		}
		return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),"分数计算失败请稍后再试");
	}
	
	@PostMapping("/savepoint")
	public BaseResponseVO savePoint(PerformanceReqVO reqVo,String score,String revisedScore, String type,@SessionGain("user") UserDTO user){
		PsCEpDocVwPrimary primary = new PsCEpDocVwPrimary();
		primary.setcEpAppraisalId(reqVo.getDocid());
		primary.setcTransactionNbr(reqVo.getcTransactionNbr());
		primary.setcWfType(WfTypeEnum.WF_STYPE_EPEV.getType());
		primary.setOprid(user.getOprId());
		primary.setVersion(new BigDecimal(reqVo.getVersion()));
		primary.setcEpPhase(reqVo.getEpPhase());
		primary.setSeqnbr(new BigDecimal(reqVo.getSeqnbr()));
		PsCEpDocVw docVw = performancePlanService.getepdoc(primary);
		if(docVw==null){
			return buildRespone(BaseRetCode.CODE_ERROR_REQUEST_PARAM_NULL);
		}
		//如果score为空说明前端没有计算分数。这里要计算一下
		if(StringUtils.isBlank(score)){
			Map<String, String> result = performancePlanService.calcPoint(reqVo.getDocid(), reqVo.getVersion(), user.getEmplId());
			if(result!=null&&"Y".equals(result.get("FLAG"))){
				if("A".equals(docVw.getcEvaType())){
					score = result.get("C_EP_SCORE");
				}else{
					score = result.get("C_EP_GRADE");
				}
			}else if(result!=null){
				return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),result.get("COMMENTS"));
			}else{
				return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),"分数计算失败请稍后再试");
			}
		}
		PsCEpAppRole role = performancePlanService.updAppRole(docVw, score, revisedScore, reqVo.getComments(), user.getEmplId(),type);
		if(role==null){
			return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),"分数保存失败请稍后再试");
		}
		if(StringUtils.isNotBlank(type)&&"submit".equals(type)){
			Map<String, String> statusResult = performancePlanService.changeDocStatus(reqVo.getDocid(), reqVo.getVersion());
			if(statusResult!=null&&StringUtils.isNotBlank(statusResult.get("COMMENTS"))){
				return buildRespone(BaseRetCode.CODE_ERROR_SYS.getRetCode(),statusResult.get("COMMENTS"));
			}
		}
		return buildRespone();
	}
	
	
}
